package cqrtplm.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hustcad.plm.basic.dto.defaultvalue.TyplmAttrDefaultValueDTO;
import com.hustcad.plm.basic.dto.defaultvalue.TyplmDefaultValueDTO;
import com.hustcad.plm.basic.dto.defaultvalue.TyplmDefaultValueParamDTO;
import com.hustcad.plm.basic.util.TyplmEntityBaseUtil;
import com.hustcad.plm.pdm.classification.model.dto.TyplmClassificationEntityDTO;
import com.hustcad.plm.pdm.classification.model.dto.TyplmClassificationRelentityDTO;
import com.hustcad.plm.pdm.classification.model.vo.TyplmClassificationVO;
import com.hustcad.plm.pdm.classification.service.TyplmClassificationCacheService;
import com.hustcad.plm.pdm.classification.service.TyplmClassificationRootService;
import com.hustcad.plm.pdm.classification.service.TyplmClassificationService;
import com.hustcad.plm.pdm.code.model.dto.TyplmCodeBaseDTO;
import com.hustcad.plm.pdm.code.service.TyplmCodeService;
import com.hustcad.plm.pdm.common.model.dto.search.SearchConditionDTO;
import com.hustcad.plm.pdm.common.model.vo.search.ResultEntityVO;
import com.hustcad.plm.pdm.common.service.search.TyplmClassifySearchService;
import com.hustcad.plm.pdm.constraint.model.dto.TyplmConstraintQueryDTO;
import com.hustcad.plm.pdm.constraint.model.dto.TyplmCreateConstraintDTO;
import com.hustcad.plm.pdm.constraint.model.vo.TyplmConstraintEditVO;
import com.hustcad.plm.pdm.constraint.model.vo.TyplmConstraintRuleDefVO;
import com.hustcad.plm.pdm.constraint.service.TyplmConstraintExtService;
import com.hustcad.plm.pdm.defaultvalue.TyplmDefaultValueService;
import com.hustcad.plm.pdm.enumeration.mapper.TyplmEnumerationMapper;
import com.hustcad.plm.pdm.enumeration.model.dto.EnumerationInputDTO;
import com.hustcad.plm.pdm.enumeration.model.dto.HandleEnumItemDTO;
import com.hustcad.plm.pdm.enumeration.model.vo.EnumerationItemHandleVO;
import com.hustcad.plm.pdm.enumeration.model.vo.LocalValueVO;
import com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationItemService;
import com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationService;
import com.hustcad.plm.pdm.enumeration.service.TyplmLocalePropertyValueService;
import com.hustcad.plm.pdm.iba.model.dto.SaveObjIBADTO;
import com.hustcad.plm.pdm.iba.model.dto.TyplmAttributeDefMapDTO;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeDefService;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeDefaultValueService;
import com.hustcad.plm.pdm.iba.service.TyplmAttributeValueService;
import com.hustcad.plm.pdm.partbom.enums.PartBomErrorCodeEnum;
import com.hustcad.plm.pdm.type.model.dto.TypeAttrDTO;
import com.hustcad.plm.pdm.type.service.TyplmTypeService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.dto.constraint.IbaDTO;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.enumeration.EnumerationDefDO;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.entity.type.ClassificationDO;
import com.ty.basic.exception.message.SystemErrorCodeEnum;
import com.ty.basic.response.ResponseResult;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import com.ty.basic.utils.ArgumentUtils;
import com.ty.basic.vo.AttributeVO;
import com.ty.basic.vo.TyAttributeDefMapVO;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.dto.*;
import cqrtplm.entity.DescribeSpliceRuleDO;
import cqrtplm.entity.MaterialSapSyncDO;
import cqrtplm.mapper.*;
import cqrtplm.service.CodeSequenceService;
import cqrtplm.service.FlowCodeService;
import cqrtplm.service.HistoryDataImportService;
import cqrtplm.service.RTAttributeCardService;
import cqrtplm.service.RTClassificationService;
import cqrtplm.vo.DescriptionRuleVO;
import cqrtplm.vo.DescriptionVO;
import liquibase.pro.packaged.A;
import liquibase.pro.packaged.S;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.RecordFormatException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static cqrtplm.constant.RTPlmConstant.TY_MPMOPERATION_TYPE_PRODUCTODER;

@Service
@Slf4j
public class RTClassificationServiceImpl implements RTClassificationService {


    private static final String MAP_SEPARATOR = "\\|";
    private static final String KEY_VALUE_SEPARATOR = "_";

    @Resource
    private FlowCodeService flowCodeService;
    @Resource
    private RTClassificationMapper rtClassificationMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private TyplmCodeService typlmCodeService;
    @Resource
    private TyplmClassificationService typlmClassificationService;
    @Resource
    private TyplmTypeService typlmTypeService;
    @Resource
    private TyplmConstraintExtService typlmConstraintExtService;
    @Resource
    private ProcessNumberMapper processNumberMapper;
    @Resource
    private TyplmDefaultValueService typlmDefaultValueService;
    @Resource
    private TyplmClassifySearchService typlmClassifySearchService;
    @Resource
    private TyplmAttributeValueService typlmAttributeValueService;
    @Resource
    private TyplmAttributeDefService typlmAttributeDefService;
    @Resource
    private DescribeSpliceRuleMapper describeSpliceRuleMapper;
    @Resource
    private RTEnumMapper rtEnumMapper;
    @Resource
    private RTAttributeCardService rtAttributeCardService;
    @Resource
    private TyplmClassificationRootService typlmClassificationRootService;
    @Resource
    private TyplmEnumerationService typlmEnumerationService;
    @Resource
    private HistoryDataImportService historyDataImportService;
    @Resource
    private TyplmAttributeDefaultValueService typlmAttributeDefaultValueService;
    @Resource
    private TyplmClassificationCacheService typlmClassificationCacheService;
    @Resource
    private TyplmLocalePropertyValueService typlmLocalePropertyValueService;
    @Resource
    private CodeSequenceService codeSequenceService;
    @Resource
    private MaterialSapSyncMapper materialSapSyncMapper;
    @Resource
    private TyplmEnumerationMapper typlmEnumerationMapper;
    @Resource
    private RTTypeClassMapper rtTypeClassMapper;
    @Resource
    private TyplmEnumerationItemService typlmEnumerationItemService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importClassification(ImportClassificationDTO importClassificationDTO) throws Exception {
        log.info("开始解析文档");
        MultipartFile file = importClassificationDTO.getFile();
        String rootId = importClassificationDTO.getRootId();
        List<ImportCategoryAttributeCardDTO> categoryAttributeCardDTOS = getCategoryAttributeCardDTOS(file);
        Map<String, CategoryAttributeCardDTO> map = CategoryAttributeCardDTO.convert(categoryAttributeCardDTOS);
        log.info("categoryAttributeCardDTOList===> : {}", map.size());
        //获取跟分类
        List<TyplmClassificationEntityDTO> classRootDTOList = this.typlmClassificationRootService.queryClassificationRootByLanguage();
        List<TyplmClassificationEntityDTO> partClassRoot = classRootDTOList.stream().filter(item -> ("零部件").equals(item.getDisplayName())).collect(Collectors.toList());

        long start = System.currentTimeMillis();
        log.info("开始处理分类 ===> 开始时间: {}", start);
        int i = 0;
        List<TyplmConstraintRuleDefVO> enumDiscreteSetConstraintVOS = new ArrayList<>();
        TyplmConstraintRuleDefVO enumDiscreteSetConstraintVO = new TyplmConstraintRuleDefVO();
        enumDiscreteSetConstraintVO.setKey("EnumDiscreteSetConstraint");
        enumDiscreteSetConstraintVO.setName("枚举值列表");
        enumDiscreteSetConstraintVO.setDataType("枚举值");
        enumDiscreteSetConstraintVO.setOid("15818");
        enumDiscreteSetConstraintVO.setOtype(TableTypeConstrant.TY_CONSTRAINTRULEDEF_OTYPE);
        enumDiscreteSetConstraintVOS.add(enumDiscreteSetConstraintVO);
        BigInteger ibaGroupId = rtClassificationMapper.selectIbaGroupId("SXKP");
        BigInteger enumGroupId = rtEnumMapper.selectEnumGroupId("Attribute Card Enums");
        String classRootId = partClassRoot.get(0).getId();
        List<CategoryAttributeCardDTO> createErrorList = new ArrayList<>();
        for (CategoryAttributeCardDTO dto : map.values()) {
            log.info("处理分类第:{}个", i++);
            log.info("处理分类内部名称:{}，显示名称: {}", dto.getCategoryInName(), dto.getCategoryDisName());
            List<AttributeCardDTO> attributeList = dto.getAttributeList();
            String isHiddenModelNumber = dto.getIsHiddenModelNumber();
            List<ClassificationDO> classificationDOS = typlmClassificationService.queryClassificationByName(
                    dto.getCategoryType() + "_" + dto.getCategoryInName());
            if (CollUtil.isNotEmpty(classificationDOS)) {
                //已存在 导入
                ClassificationDO classificationDO = classificationDOS.get(0);
                log.info("分类已存在：{}", dto.getCategoryInName());
                //处理iba属性
                if (CollUtil.isNotEmpty(attributeList)) {
                    IdentifierEntity classEntity = classificationDO.getIdentifierRef();
                    //保存分类码
                    if ("P".equals(dto.getCategoryCode())) {
                        if (StringUtils.isNotEmpty(dto.getCategoryCode()) && StringUtils.isNotBlank(
                                dto.getCategoryCode())) {
                            saveClassificationCode(dto.getCategoryCode(), classEntity);
                        }
                    }
                    //更新描述规则
                    historyDataImportService.updateDescribeRule(attributeList, classEntity, isHiddenModelNumber);
                    // 更新iba属性
                    List<String> keyNames = attributeList.stream().map(AttributeCardDTO::getAttributeInName).collect(
                            Collectors.toList());
                    List<AttributeVO> attributeVOSList = typlmAttributeDefService.queryAttrDefByNameList(keyNames);
                    Map<String, AttributeCardDTO> attributeMap = buildAttributeMap(attributeList);

                    Set<String> attributeNames = attributeVOSList.stream().map(AttributeVO::getAttributeDefName)
                            .collect(
                                    Collectors.toSet());
                    attributeList.removeIf(
                            attributeCardDTO -> attributeNames.contains(attributeCardDTO.getAttributeInName()));
                    //创建iba属性
                    if (ObjectUtil.isNotEmpty(attributeList)) {
                        rtAttributeCardService.createIbaAttribute(attributeList, ibaGroupId);
                    }
                    //                        List<String> noExistAttrKey = attributeList.stream().map(AttributeCardDTO::getAttributeInName).collect(
                    //                                Collectors.toList());
                    List<AttributeVO> attributeVOSList2 = typlmAttributeDefService.queryAttrDefByNameList(
                            new ArrayList<>(attributeNames));
                    List<TyAttributeDefMapVO> tyAttributeDefMapVOS = typlmTypeService.queryInheritAttrDef(classEntity.getOid(), classEntity.getOtype());
                    List<String> hsaExistAttr = tyAttributeDefMapVOS.stream().map(TyAttributeDefMapVO::getName).collect(
                            Collectors.toList());
                    attributeVOSList2.removeIf(item -> hsaExistAttr.contains(item.getAttributeDefName()));
                    //创建iba属性和分类卡片关联关系
                    if(CollUtil.isNotEmpty(attributeVOSList2)){
                        createClassCardAndAttrLink(attributeVOSList2, attributeMap, classEntity);
                        // 更新属性默认值 && 更新属性绑定枚举
                        updateAttrDefaultValueAndEnum(attributeMap, classEntity, dto, enumDiscreteSetConstraintVOS,
                                                      enumGroupId);
                    }
                }
            } else {
                // 创建分类
                TyplmClassificationEntityDTO classInfo = createClassAttrCard(dto, rootId, classRootId);
                IdentifierEntity classEntity = new IdentifierEntity(new BigInteger(classInfo.getId()),
                                                                    classInfo.getOtype());
                log.info("创建分类：{}", dto.getCategoryInName());
                RTAttributeCardDTO rtAttributeCardDTO = new RTAttributeCardDTO();
                rtAttributeCardDTO.setAttributeCard(String.valueOf(classInfo.getId()));
                rtAttributeCardDTO.setAttributeCardDisplayName(classInfo.getDisplayName());
                String categoryInName = dto.getCategoryInName();
                if (categoryInName.contains("_")) {
                    String[] split = categoryInName.split("_");
                    if (split[0].length() == 1) {
                        rtAttributeCardDTO.setProductLine(split[0]);
                    } else {
                        rtAttributeCardDTO.setProductLine(categoryInName.substring(0, 1));
                        rtAttributeCardDTO.setDevelopmentOrder(split[0]);
                    }
                    rtAttributeCardDTO.setCategory(split[1]);
                } else {
                    rtAttributeCardDTO.setCategory(categoryInName);
                }
                String categoryType = dto.getCategoryType();
                if (!categoryType.equals("P")) {
                    if (categoryType.equals("T")) {
                        rtAttributeCardDTO.setType("图样代号");
                    } else if (categoryType.equals("W")) {
                        rtAttributeCardDTO.setType("物料码");
                    } else if (categoryType.equals("B")) {
                        rtAttributeCardDTO.setType("标准件");
                    } else if (categoryType.equals("L")) {
                        rtAttributeCardDTO.setType("EBOM号");
                        rtAttributeCardDTO.setProductLine(categoryInName.substring(0, 1));
                        rtAttributeCardDTO.setDevelopmentOrder(categoryInName);
                        rtAttributeCardDTO.setCategory("");
                    }
                    rtAttributeCardService.insert(rtAttributeCardDTO);
                }
                // 保存分类码
                if (categoryType.equals("P")) {
                    if (StringUtils.isNotEmpty(dto.getCategoryCode()) && StringUtils.isNotBlank(
                            dto.getCategoryCode())) {
                        saveClassificationCode(dto.getCategoryCode(), classEntity);
                    }
                }
                //处理iba属性
                if (CollUtil.isNotEmpty(attributeList)) {
                    //更新描述规则
                    historyDataImportService.updateDescribeRule(attributeList, classEntity, isHiddenModelNumber);
                    Map<String, AttributeCardDTO> attributeMap = buildAttributeMap(attributeList);

                    List<String> keyNames = attributeList.stream().map(AttributeCardDTO::getAttributeInName).collect(
                            Collectors.toList());
                    List<AttributeVO> attributeVOSList = typlmAttributeDefService.queryAttrDefByNameList(keyNames);
                    Set<String> attributeNames = attributeVOSList.stream().map(AttributeVO::getAttributeDefName)
                            .collect(
                                    Collectors.toSet());

                    attributeList.removeIf(
                            attributeCardDTO -> attributeNames.contains(attributeCardDTO.getAttributeInName()));

                    //创建iba属性
                    if (ObjectUtil.isNotEmpty(attributeList)) {
                        rtAttributeCardService.createIbaAttribute(attributeList, ibaGroupId);
                    }
                    List<AttributeVO> attributeVOSList2 = typlmAttributeDefService.queryAttrDefByNameList(keyNames);
                    //创建iba属性和分类卡片关联关系
                    createClassCardAndAttrLink(attributeVOSList2, attributeMap, classEntity);

                    // 更新属性默认值 && 更新属性绑定枚举
                    long enumstart = System.currentTimeMillis();
                    updateAttrDefaultValueAndEnum(attributeMap, classEntity, dto, enumDiscreteSetConstraintVOS,
                                                  enumGroupId);
                    log.info("枚举耗时 ===> 耗时: {}", System.currentTimeMillis() - enumstart);
                }
            }
        }
        log.info("总计{}个，创建失败:{}个", map.size(), createErrorList.size());
        log.info("创建失败列表:{}", createErrorList);
        log.info("属性卡片处理完成 ===> 耗时: {}", System.currentTimeMillis()- start);
    }

    private void saveClassificationCode(String categoryCode, IdentifierEntity classEntity) {
        TyplmCodeBaseDTO info = this.typlmCodeService.queryCodeBaseDTOByBaseoid(classEntity);
        if(ObjectUtil.isNotEmpty(info) && info.getObjectnumber().equals(categoryCode)){
            return;
        }
        TyplmCodeBaseDTO codeBaseDTO = new TyplmCodeBaseDTO();
        codeBaseDTO.setBaseoid(classEntity.getOid());
        codeBaseDTO.setOtype(classEntity.getOtype());
        codeBaseDTO.setBaseotype(classEntity.getOtype());
        codeBaseDTO.setObjectnumber(categoryCode);
        this.typlmCodeService.saveCodeBaseInfo(codeBaseDTO);
    }

    private Map<String, AttributeCardDTO> buildAttributeMap(List<AttributeCardDTO> attributeList) {
        return attributeList.stream()
                .filter(Objects::nonNull)
                .filter(item -> item.getAttributeInName() != null)
                .collect(Collectors.toMap(
                        AttributeCardDTO::getAttributeInName,
                        Function.identity(),
                        (oldValue, newValue) -> oldValue
                ));
    }

    /**
     * 创建iba属性和分类卡片关联关系
     */
    @Override
    public void createClassCardAndAttrLink(List<AttributeVO> attributeVOSList2, Map<String, AttributeCardDTO> attributeMap , IdentifierEntity classEntity) {
        List<TypeAttrDTO> typeAttrDTOList = new ArrayList<>();
        List<TyAttributeDefMapVO> attrDefMapList = this.typlmTypeService.queryInheritAttrDef(classEntity.getOid(), classEntity.getOtype());
        List<String> existIban = attrDefMapList.stream().filter(item -> "0".equals(item.getIsInherit())).map(
                TyAttributeDefMapVO::getName).collect(Collectors.toList());
        for (AttributeVO attributeVO : attributeVOSList2) {
            if(existIban.contains(attributeVO.getAttributeDefName())){
                continue;
            }
            AttributeCardDTO attributeCardDTO = attributeMap.get(attributeVO.getAttributeDefName());
            TypeAttrDTO typeAttrDTO = new TypeAttrDTO();
            typeAttrDTO.setOid(attributeVO.getOid());
            typeAttrDTO.setOType(attributeVO.getOType());
            typeAttrDTO.setName(attributeVO.getAttributeDefName());
            typeAttrDTO.setDisplayName(attributeCardDTO.getAttributeDisName());
            typeAttrDTO.setDescription(attributeCardDTO.getAttributeNo());
            typeAttrDTOList.add(typeAttrDTO);
        }
        if(!typeAttrDTOList.isEmpty()){
            typlmTypeService.batchSaveTypeAttributeMap(classEntity, typeAttrDTOList);
        }

    }

    /**
     * 创建分类
     *
     */
    @Override
    public TyplmClassificationEntityDTO createClassAttrCard(CategoryAttributeCardDTO dto, String parentId,
                                                             String classRootId) {
        TyplmClassificationRelentityDTO typlmClassificationRelentityDTO = new TyplmClassificationRelentityDTO();
        typlmClassificationRelentityDTO.setId(parentId);
        typlmClassificationRelentityDTO.setRootid(classRootId);
        TyplmClassificationEntityDTO typlmClassificationEntityDTO = new TyplmClassificationEntityDTO();
        String categoryInName = dto.getCategoryInName();
        String disName = dto.getCategoryInName();
        if("W".equals(dto.getCategoryType())){
            categoryInName = "W_" + dto.getCategoryInName();
            disName = disName + "_物料码";
        }else if("T".equals(dto.getCategoryType())){
            categoryInName = "T_" + dto.getCategoryInName();
            disName = disName + "_图样代号";
        } else if("B".equals(dto.getCategoryType())){
            categoryInName = "B_" + dto.getCategoryInName();
            disName = disName + "_标准件";
        } else if("L".equals(dto.getCategoryType())){
            categoryInName = "L_" + dto.getCategoryInName();
        }
        if("P".equals(dto.getCategoryType())){
            typlmClassificationEntityDTO.setDisplayName(dto.getCategoryDisName());
        }else {
            typlmClassificationEntityDTO.setDisplayName(disName);
        }
        typlmClassificationEntityDTO.setInstantiable(1);
        typlmClassificationEntityDTO.setInternalName(categoryInName);
        //创建分类
        return typlmClassificationService.insertClassification(
                typlmClassificationEntityDTO, typlmClassificationRelentityDTO);

    }

    /**
     * 更新iba属性默认值和枚举
     *
     */
    @Override
    public void updateAttrDefaultValueAndEnum(Map<String, AttributeCardDTO> attributeMap, IdentifierEntity classEntity, CategoryAttributeCardDTO dto,
                                               List<TyplmConstraintRuleDefVO> enumDiscreteSetConstraint, BigInteger enumGroupId) {
        List<TyAttributeDefMapVO> tyAttributeDefMapVOS = typlmTypeService.queryInheritAttrDef(classEntity.getOid(), classEntity.getOtype());
        if(CollUtil.isEmpty(tyAttributeDefMapVOS)){
            return;
        }
        for (TyAttributeDefMapVO tyAttributeDefMapVO : tyAttributeDefMapVOS) {
            String defMapVOName = tyAttributeDefMapVO.getName();
            if (attributeMap.containsKey(defMapVOName)) {
                AttributeCardDTO attributeCardDTO = attributeMap.get(defMapVOName);

                //更新默认值
//                String defaultValue = attributeCardDTO.getDefaultValue();
//                updateAttributeDefaultValue(tyAttributeDefMapVO, classEntity, defaultValue);

                //更新绑定枚举
                if (CollUtil.isNotEmpty(attributeCardDTO.getEnumMap())) {
                    TyplmConstraintQueryDTO constraintQueryDTO = new TyplmConstraintQueryDTO();
                    constraintQueryDTO.setAttributereferenceoid(tyAttributeDefMapVO.getOid());
                    constraintQueryDTO.setAttributereferenceotype(tyAttributeDefMapVO.getOtype());
                    //存在枚举 删除
                    List<TyplmConstraintEditVO> constraintEditVOS = this.typlmConstraintExtService.getEntityConstraint(
                            Collections.singletonList(constraintQueryDTO));
                    if (CollUtil.isNotEmpty(constraintEditVOS)) {
                        List<TyplmConstraintEditVO> constraintEditVOList = constraintEditVOS.stream().filter(
                                typlmConstraintEditVO -> typlmConstraintEditVO.getKey()
                                        .equals("EnumDiscreteSetConstraint")).collect(
                                Collectors.toList());

                        if (CollUtil.isNotEmpty(constraintEditVOList)) {
                            for (TyplmConstraintEditVO typlmConstraintEditVO : constraintEditVOList) {
                                this.typlmConstraintExtService.deleteConstraint(typlmConstraintEditVO);
                            }
                        }
                    }

                    TyplmCreateConstraintDTO createConstraintDTO = new TyplmCreateConstraintDTO();
                    createConstraintDTO.setRuleReferenceOid(classEntity.getOid());
                    createConstraintDTO.setRuleReferenceOtype(classEntity.getOtype());
                    createConstraintDTO.setEntity(
                            new IdentifierEntity(tyAttributeDefMapVO.getOid(), tyAttributeDefMapVO.getOtype()));
                    createConstraintDTO.setConstraintRuleDefVOS(enumDiscreteSetConstraint);
                    List<TyplmConstraintEditVO> entityConstraint = this.typlmConstraintExtService.createEntityConstraint(
                            createConstraintDTO);
                    //设置属性配枚举
                    TyplmConstraintEditVO typlmConstraintEditVO = entityConstraint.get(0);
                    typlmConstraintEditVO.setEnumoid(createEnum(attributeCardDTO, enumGroupId,tyAttributeDefMapVO.getOid()));
                    typlmConstraintEditVO.setEnumotype(TableTypeConstrant.TY_ENUMERATIONDEF_OTYPE);
                    typlmConstraintExtService.batchUpdateEntityConstraint(entityConstraint);
                }
            }
        }
    }

    /**
     * 更新分类属性显示名称
     * @param classificationOid
     * @param type
     */
    @Override
    public void classificationOperator(BigInteger classificationOid, String type) {
        TyplmClassificationEntityDTO cf = typlmClassificationService.queryClassificationDTOByOID(classificationOid);
        String displayName = cf.getDisplayName();
        if (log.isInfoEnabled()) {
            log.info("classification===>{}", cf);
            log.info("getName2===>{}", displayName);
        }

        IdentifierEntity itemInfoEntity = new IdentifierEntity();
        itemInfoEntity.setOid(classificationOid);
        itemInfoEntity.setOtype(cf.getOtype());
        LocalValueVO localValueVO = this.typlmLocalePropertyValueService.queryTypeLocalePropertyValue(itemInfoEntity,
                                                                                                      "displayName");
        if(org.apache.commons.lang3.StringUtils.equalsIgnoreCase("checkOut",type)){
            if (!displayName.contains("-已检出")){
                localValueVO.setValue(displayName + "-已检出");
            }
        } else if (org.apache.commons.lang3.StringUtils.equalsIgnoreCase("checkIn",type)) {
            if (displayName.contains("-已检出")){
                localValueVO.setValue(displayName.replaceAll("-已检出",""));
            }
        }

        this.typlmLocalePropertyValueService.updateTypeLocalePropertyValue(localValueVO);
    }


    private String createEnum(AttributeCardDTO attributeCardDTO, BigInteger enumGroupId, BigInteger attributeOid) {
        EnumerationInputDTO inputDTO = new EnumerationInputDTO();
        Map<String, String> enumItemMap = attributeCardDTO.getEnumMap();
        String description = enumItemMap.keySet().stream().collect(Collectors.joining(""));
        List<EnumerationDefDO> enumDefs = null;
        String attributeInName = attributeCardDTO.getAttributeInName();
        if(attributeInName.contains("|")){
            attributeInName = attributeInName.split("\\|")[1];
        }
        if (ObjectUtil.isEmpty(enumDefs)) {
            String code = processNumberMapper.generateEnumDefCode();
            inputDTO.setDisplayName(attributeCardDTO.getAttributeDisName() + "_" + code);
            inputDTO.setName("@_@"+ code);
            inputDTO.setParentNodeOid(enumGroupId);
            inputDTO.setParentNodeOtype(TableTypeConstrant.TY_ENUMERATIONGROUP_OTYPE);
            inputDTO.setIscolored(1);
            BigInteger enumId = typlmEnumerationService.createEnumDef(inputDTO).getOid();
            if(attributeInName.contains(";;;")){
                attributeInName = attributeInName.split(";;;")[1];
            }
            List<EnumerationDefDO> parentEnumDefs = typlmEnumerationService.queryEnumDefByNames(
                    Collections.singletonList(attributeInName));
            JSONObject select = rtEnumMapper.select(String.valueOf(attributeOid));
            if(select != null){
                rtEnumMapper.delete(String.valueOf(attributeOid));
            }
            if(CollUtil.isNotEmpty(parentEnumDefs)){
                rtEnumMapper.insertEnumDescription(String.valueOf(enumId), description,
                                                   String.valueOf(attributeOid),
                                                   String.valueOf(parentEnumDefs.get(0).getOid()));
            }else {
                rtEnumMapper.insertEnumDescription(String.valueOf(enumId), description,
                                                   String.valueOf(attributeOid),
                                                   "1");
            }
            HandleEnumItemDTO handleEnumItemDTO = new HandleEnumItemDTO();
            List<EnumerationItemHandleVO> enumItemList = new ArrayList<>();
            for (String enumItemId : enumItemMap.keySet()) {
                String enumItemValue = enumItemMap.get(enumItemId);
                EnumerationItemHandleVO enumItemHandleVO = new EnumerationItemHandleVO();
                enumItemHandleVO.setDisplayName(enumItemValue);
                enumItemHandleVO.setDisplayNameCn(enumItemValue);
                enumItemHandleVO.setName(enumItemId);
                enumItemHandleVO.setDescription(enumItemValue);
                enumItemHandleVO.setState("true");
                enumItemHandleVO.setName(enumItemId);
                enumItemHandleVO.setInternalName(enumItemId);
                enumItemList.add(enumItemHandleVO);
            }
            handleEnumItemDTO.setDefoid(enumId);
            handleEnumItemDTO.setEnumItemList(enumItemList);
            typlmEnumerationService.handleEnumItemList(handleEnumItemDTO);
            return String.valueOf(enumId);
        }else {
            List<EnumerationDefDO> parentEnumDefs = typlmEnumerationService.queryEnumDefByNames(
                    Collections.singletonList(attributeInName));
            JSONObject data = rtEnumMapper.select(String.valueOf(attributeOid));
            if(!ObjectUtil.isEmpty(data)){
                rtEnumMapper.delete(String.valueOf(attributeOid));
            }
            if(CollUtil.isNotEmpty(parentEnumDefs)){
                rtEnumMapper.insertEnumDescription(String.valueOf(enumDefs.get(0).getOid()), description,
                                                   String.valueOf(attributeOid),
                                                   String.valueOf(parentEnumDefs.get(0).getOid()));
            }else {
                rtEnumMapper.insertEnumDescription(String.valueOf(enumDefs.get(0).getOid()), description,
                                                   String.valueOf(attributeOid),
                                                   "1");
            }
            return String.valueOf(enumDefs.get(0).getOid());
        }
    }


    /**
     * 更新默认值
     */
    private void updateAttributeDefaultValue(TyAttributeDefMapVO attributeVO, IdentifierEntity entity, String defaultValue) {
        //获取属性默认值
        TyplmDefaultValueParamDTO typlmDefaultValueParamDTO = new TyplmDefaultValueParamDTO();

        typlmDefaultValueParamDTO.setEntity(
                new IdentifierEntity(attributeVO.getOid(),
                                     TableTypeConstrant.TY_ATTRIBUTE_DEF_MAP_OTYPE));
        typlmDefaultValueParamDTO.setContext(
                new IdentifierEntity(entity.getOid(), TableTypeConstrant.TY_TYPE_OTYPE));
        Map<String, TyplmDefaultValueParamDTO> defaultValueParamMap = new HashMap<>();
        defaultValueParamMap.put(TableTypeConstrant.TY_TYPE_OTYPE + ":" + entity.getOid(), typlmDefaultValueParamDTO);
        //查询默认值
        Map<String, List<TyplmAttrDefaultValueDTO>> entityDefaultValueList = this.typlmDefaultValueService.getEntityDefaultValueList(
                defaultValueParamMap);
        //如果默认值存在 删除
        if(CollUtil.isNotEmpty(entityDefaultValueList)){
            entityDefaultValueList.values().stream()
                    .filter(CollUtil::isNotEmpty)
                    .flatMap(List::stream)
                    .forEach(dto -> this.typlmAttributeDefaultValueService.deleteAttributeDefaultValue(dto.getOid()));
        }
        //添加新的枚举
        TyplmDefaultValueDTO typlmDefaultValueDTO = new TyplmDefaultValueDTO();
        typlmDefaultValueDTO.setValue(defaultValue);
        typlmDefaultValueParamDTO.setDefaultValue(typlmDefaultValueDTO);
        this.typlmDefaultValueService.createEntityDefaultValue(Collections.singletonList(typlmDefaultValueParamDTO));
    }

    @Override
    public List<ImportCategoryAttributeCardDTO> getCategoryAttributeCardDTOS(MultipartFile file) {
        // 设置POI数组大小限制（需大于报错值158,460,277）
        IOUtils.setByteArrayMaxOverride(160_000_000);

        List<ImportCategoryAttributeCardDTO> dataList;
        try (InputStream inputStream = file.getInputStream()) {
            // 使用EasyExcel读取数据
            dataList = EasyExcel.read(inputStream, ImportCategoryAttributeCardDTO.class, null)
                    .sheet()
                    .doReadSync();
        } catch (IOException e) {
            throw new RuntimeException("读取Excel文件失败", e);
        } catch (RuntimeException e) {
            // 捕获POI可能的内存限制异常
            if (e.getCause() instanceof RecordFormatException) {
                // 尝试二次扩容 (根据实际需要调整)
                IOUtils.setByteArrayMaxOverride(200_000_000);
                try (InputStream is = file.getInputStream()) {
                    dataList = EasyExcel.read(is, ImportCategoryAttributeCardDTO.class, null)
                            .sheet()
                            .doReadSync();
                } catch (IOException ex) {
                    throw new RuntimeException("二次读取失败", ex);
                }
            } else {
                throw e;
            }
        }

        // 过滤掉空行 (保留有数据的行)
        List<ImportCategoryAttributeCardDTO> nonEmptyList = dataList.stream()
                .filter(ImportCategoryAttributeCardDTO::isRowEmpty) // 注意取反操作
                .collect(Collectors.toList());

        // 正确校验：当没有有效数据时才抛异常
        if (CollUtil.isEmpty(nonEmptyList)) {
            throw SystemErrorCodeEnum.EXCEL_READ_EXCEPTION.getException("Excel中未找到有效数据");
        }

        return nonEmptyList;
    }

    @Override
    @Transactional
    public void updateClassifyTree(RTClassifyTreeDTO rtClassifyTreeDTO) {
        BigInteger newRootId = rtClassificationMapper.getRootIdByClassificationId(rtClassifyTreeDTO.getParentID());
        if (newRootId == null) {
            // 如果新父节点是根节点，则使用自身作为根节点
            rtClassificationMapper.updateClassificationParent(
                    rtClassifyTreeDTO.getOid(),
                    BigInteger.ZERO,    // parentnodeoid = 0
                    rtClassifyTreeDTO.getParentID() // CLASSFICATIONROOTOID = 父分类ID
            );
        } else {
            // 2. 更新当前分类的父节点和根节点
            rtClassificationMapper.updateClassificationParent(
                    rtClassifyTreeDTO.getOid(),
                    rtClassifyTreeDTO.getParentID(),
                    newRootId
            );
        }
        // 3. 递归获取所有子节点ID
        List<BigInteger> descendantIds = rtClassificationMapper.findAllDescendantIds(rtClassifyTreeDTO.getOid());
        if (CollUtil.isNotEmpty(descendantIds)) {
            BigInteger rootIdForDescendants = (newRootId == null) ? rtClassifyTreeDTO.getParentID() : newRootId;
            rtClassificationMapper.batchUpdateRootId(descendantIds, rootIdForDescendants);
        }
    }

    @Override
    @Transactional
    public String addDevelopmentOrder(RTProductDevelopmentOrderDTO rtProductDevelopmentOrderDTO) {
        TyplmEntityBaseUtil.fillCommonFieldForCreate(rtProductDevelopmentOrderDTO);
        rtProductDevelopmentOrderDTO.setOtype(TY_MPMOPERATION_TYPE_PRODUCTODER);
        rtProductDevelopmentOrderDTO.setOid((snowflakeIdComponent.getInstance().nextId()));
        String orderNumber = generateOrderNumber(rtProductDevelopmentOrderDTO.getProductLineCode());
        rtProductDevelopmentOrderDTO.setOrderNumber(orderNumber);
        rtClassificationMapper.insertProductOrder(rtProductDevelopmentOrderDTO);
        return orderNumber;
    }

    private String generateOrderNumber(String productLineCode) {
        // 使用产品线编码作为锁对象
        synchronized (productLineCode.intern()) {
            // 查询当前最大流水号
            String currentMaxSequence = rtClassificationMapper.selectMaxSequenceNumber(productLineCode);
            // 生成下一个流水号
            String nextSequence = flowCodeService.getNextFlowCode(currentMaxSequence);
            // 拼接完整订单号
            return productLineCode + nextSequence;
        }
    }


    @Override
    public ResponseResult<RTProductDevelopmentOrderDTO> queryProjectDetailByOid(
            RTProductDevelopmentOrderDTO rtProductDevelopmentOrderDTO) {
        ArgumentUtils.checkArgumentNull(rtProductDevelopmentOrderDTO.getEntity().getOid(), PartBomErrorCodeEnum.EXCEPTION_PARAM.getLocaleMessage("分类"));
        TyplmCodeBaseDTO typlmCodeBaseDTO = typlmCodeService.queryCodeBaseDTOByBaseoid(
                rtProductDevelopmentOrderDTO.getEntity());
        if (ObjectUtil.isNull(typlmCodeBaseDTO)){
            throw  RTErrorCodeEnum.OBJECT_NOT_EXIST.getException("当前分类编码不存在");
        }
        if(ObjectUtil.isEmpty(typlmCodeBaseDTO.getObjectnumber())){
            throw  RTErrorCodeEnum.OBJECTNUMBER_NOT_EXIST.getException("当前分类产品线不存在，创建开发令失败");
        }
        String ProductName = rtClassificationMapper.queryProductName(rtProductDevelopmentOrderDTO.getEntity().getOid());
        rtProductDevelopmentOrderDTO.getProductDevelopmentOrderMap().put(typlmCodeBaseDTO.getObjectnumber(),
                                                                         ProductName);
        return ResponseResult.success(rtProductDevelopmentOrderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAttributeByClassification(AttributeAndClassificationDTO dto) {
        String classId = dto.getClassId();
        List<String> attributeIds = dto.getAttributeIds();
        Map<String, TyplmDefaultValueParamDTO> defaultValueParamMap = new HashMap<>();

        List<TyplmAttrDefaultValueDTO> entityDefaultValueList = new ArrayList<>();
        //获取属性默认值
        for (String attributeId : attributeIds) {
            TyplmDefaultValueParamDTO typlmDefaultValueParamDTO = new TyplmDefaultValueParamDTO();
            typlmDefaultValueParamDTO.setEntity(
                    new IdentifierEntity(new BigInteger(attributeId), TableTypeConstrant.TY_ATTRIBUTE_DEF_MAP_OTYPE));
            typlmDefaultValueParamDTO.setContext(
                    new IdentifierEntity(new BigInteger(classId), TableTypeConstrant.TY_TYPE_OTYPE));
            defaultValueParamMap.put(TableTypeConstrant.TY_TYPE_OTYPE + ":" + classId, typlmDefaultValueParamDTO);
            Map<String, List<TyplmAttrDefaultValueDTO>> entityDefaultValueList1 = typlmDefaultValueService.getEntityDefaultValueList(
                    defaultValueParamMap);
            if(CollUtil.isEmpty(entityDefaultValueList1)){
                throw RTErrorCodeEnum.DEV_CODE_EXIST.getException("勾选的属性未设置默认值,请先设置默认值!");
            }
            entityDefaultValueList.addAll(entityDefaultValueList1.get(TableTypeConstrant.TY_TYPE_OTYPE + ":" + classId));
        }

        //收集默认值
        Map<BigInteger, String> defaultValueMap = new HashMap<>();
        for(TyplmAttrDefaultValueDTO defaultValueDTO : entityDefaultValueList){
            if (StringUtils.isNotBlank(defaultValueDTO.getDefaultValue())) {
                defaultValueMap.put(defaultValueDTO.getAttributeReferenceOid(), defaultValueDTO.getDefaultValue());
            }
        }

        //查询iba属性
        List<TyplmAttributeDefMapDTO> typlmAttributeDefMapDTOS = typlmAttributeDefService.batchQueryAttributeMap(
                new ArrayList<>(defaultValueMap.keySet()));
        Map<BigInteger, TyplmAttributeDefMapDTO> typlmAttributeDefMapDTOMap = typlmAttributeDefMapDTOS.stream()
                .collect(Collectors.toMap(TyplmAttributeDefMapDTO::getAttributereferenceoid, Function.identity()));

        //收集名称
        List<String> ibaNameList = typlmAttributeDefMapDTOS.stream()
                .map(TyplmAttributeDefMapDTO::getName)
                .collect(Collectors.toList());

        TyplmClassificationEntityDTO currentClassInfo = new TyplmClassificationEntityDTO();
        //收集所有物料
        Map<String, List<ResultEntityVO>> partMap = new HashMap<>();
        //根据页面选择的分类查询所有层级的子分类
        List<TyplmClassificationVO> resultList = this.typlmClassificationCacheService.queryClassificationByParentID(
                new BigInteger(classId), "N");
        Set<String> classOidList = new HashSet<>();
        classOidList.add(classId);
        boolean isT = false;
        //查询分类实例化出来的part
        if (CollUtil.isNotEmpty(resultList)) {
            for (TyplmClassificationVO typlmClassificationVO : resultList) {
                classOidList.add(typlmClassificationVO.getId().toString());
                SearchConditionDTO conditionDTO = new SearchConditionDTO();
                conditionDTO.setPageNum(1);
                conditionDTO.setPageSize(9999999);
                conditionDTO.setClassificationOid(typlmClassificationVO.getId());
                conditionDTO.setTypeInthid(TableTypeConstrant.TY_PART_OTYPE);
                partMap.put(typlmClassificationVO.getId().toString(),
                            typlmClassifySearchService.queryByCondition(conditionDTO));
            }
        } else {//页面中选择的分类是最底层分类
            currentClassInfo = typlmClassificationService.queryClassificationDTOByOID(new BigInteger(classId));
            if(currentClassInfo != null){
                String internalName = currentClassInfo.getInternalName();
                if(StringUtils.isNotBlank(internalName)){
                    if(internalName.startsWith("T_")){
                        isT = true;
                        classOidList.add(currentClassInfo.getParentOid());
                    }
                }
            }
            classOidList.add(classId);
            SearchConditionDTO conditionDTO = new SearchConditionDTO();
            conditionDTO.setPageNum(1);
            conditionDTO.setPageSize(9999999);
            conditionDTO.setClassificationOid(new BigInteger(classId));
            conditionDTO.setTypeInthid(TableTypeConstrant.TY_PART_OTYPE);
            partMap.put(classId, typlmClassifySearchService.queryByCondition(conditionDTO));
        }

        // 收集partMap中所有ResultEntityVO的oid，过滤空值
        List<BigInteger> partOidList = partMap.values().stream()
                .filter(Objects::nonNull)  // 过滤空的List
                .flatMap(List::stream)
                .filter(Objects::nonNull)  // 过滤空的ResultEntityVO
                .map(ResultEntityVO::getOid)
                .filter(Objects::nonNull)  // 过滤空的oid
                .distinct()                // 去除重复的oid
                .collect(Collectors.toList());

        //收集分类实例出来的part对象的oid，根据oid查询实例化对象的iba
        Map<String, List<AttributeVO>> ibaValuePart = typlmAttributeValueService.getAttrValueTableByEntitys(
                partOidList, TableTypeConstrant.TY_PART_OTYPE);

        //查询拼接规则
        List<DescribeSpliceRuleDO> describeSpliceRuleDOS = describeSpliceRuleMapper.queryDescribeSpliceRuleBatch(
                classOidList, TableTypeConstrant.TY_CLASSIFICATION_OTYPE);
        Map<String, DescribeSpliceRuleDO> describeSpliceRuleDOMap = describeSpliceRuleDOS.stream()
                .collect(Collectors.toMap(
                        DescribeSpliceRuleDO::getClassOid,
                        Function.identity(),
                        (first, second) -> first  // 始终保留第一个值
                ));

        //查询出来存在拼接的分类
        Map<String, List<String>> describeMap = new HashMap<>();
        for (Map.Entry<String, DescribeSpliceRuleDO> entry : describeSpliceRuleDOMap.entrySet()) {
            String key = entry.getKey();
            String displayRules = entry.getValue().getDescribeRules();
            // 使用Stream过滤匹配的ibaName
            List<String> matchedIbaNames = ibaNameList.stream()
                    .filter(displayRules::contains)
                    .collect(Collectors.toList());
            // 只有当有匹配项时才放入map
            if (!matchedIbaNames.isEmpty()) {
                describeMap.put(key, matchedIbaNames);
            }
        }
        TyplmClassificationVO classificationAttrCache2 = typlmClassificationCacheService.getClassificationAttrByOid(
                new BigInteger(classId));
        String categoryName = classificationAttrCache2.getCategoryName();
        boolean isW = false;
        if (categoryName.startsWith("W_")) {
            if(describeMap.size() == 1){
                isW = true;
            }
        }
        if (isW || isT) {
            List<ResultEntityVO> materialCodeEntities = partMap.values().stream()
                    .filter(Objects::nonNull)  // 过滤空的List
                    .flatMap(List::stream)
                    .filter(Objects::nonNull)  // 过滤空的ResultEntityVO
                    .filter(resultEntityVO -> "MaterialCode".equals(resultEntityVO.getTypeLogicalidentifier()))
                    .collect(Collectors.toList());
            if(isT){
                partMap.put(currentClassInfo.getParentOid(), materialCodeEntities);
            }else {
                partMap.put(classId, materialCodeEntities);
            }
        }


        Map<String, List<String>> map = new HashMap<>();
        List<String> partOidS = new ArrayList<>();
        List<SaveObjIBADTO> objWithIbaList = new ArrayList<>();
        Set<BigInteger> set = new HashSet<>();
        // 批量更新属性
        for (Map.Entry<String, List<ResultEntityVO>> entry : partMap.entrySet()) {
            List<ResultEntityVO> value = entry.getValue();
            for (ResultEntityVO vo : value) {
                boolean flag = false;
                if(set.contains(vo.getOid())){
                    continue;
                }
                set.add(vo.getOid());
                SaveObjIBADTO saveObjIBADTO = new SaveObjIBADTO();
                List<IbaDTO> ibaDTOList = new ArrayList<>();
                List<AttributeVO> attributeVOS = ibaValuePart.get(vo.getOid().toString());
                for (AttributeVO attributeVO : attributeVOS) {
                    String attributeOid = attributeVO.getAttributeOid();
                    if (typlmAttributeDefMapDTOMap.containsKey(new BigInteger(attributeOid))) {
                        TyplmAttributeDefMapDTO typlmAttributeDefMapDTO = typlmAttributeDefMapDTOMap.get(
                                new BigInteger(attributeOid));
                        String attributeValue = attributeVO.getAttributeValue();
                        flag = true;
                        if (StringUtils.isBlank(attributeValue)) {
                            IbaDTO ibaDTO = new IbaDTO();
                            ibaDTO.setKey(attributeVO.getAttributeEnName());
                            ibaDTO.setValue(defaultValueMap.get(typlmAttributeDefMapDTO.getOid()));
                            ibaDTOList.add(ibaDTO);
                            map.put(attributeVO.getAttributeEnName(),
                                    Collections.singletonList(defaultValueMap.get(typlmAttributeDefMapDTO.getOid())));
                        }
                    }
                }
                if (!flag) {
                    for (Map.Entry<BigInteger, TyplmAttributeDefMapDTO> typlmAttributeDefMapDTOMapEntry : typlmAttributeDefMapDTOMap.entrySet()) {
                        TyplmAttributeDefMapDTO value1 = typlmAttributeDefMapDTOMapEntry.getValue();
                        IbaDTO ibaDTO = new IbaDTO();
                        ibaDTO.setKey(value1.getName());
                        ibaDTO.setValue(defaultValueMap.get(value1.getOid()));
                        ibaDTOList.add(ibaDTO);
                        map.put(value1.getName(),
                                Collections.singletonList(defaultValueMap.get(value1.getOid())));
                    }
                }
                if (CollUtil.isNotEmpty(ibaDTOList)) {
                    partOidS.add(vo.getOid().toString());
                    saveObjIBADTO.setObjIbaList(ibaDTOList);
                    saveObjIBADTO.setCTyEntityBaseDO(new CTyEntityBaseDO(vo.getOid(), vo.getOtype()));
                    objWithIbaList.add(saveObjIBADTO);
                }
            }
        }
        typlmAttributeValueService.batchSaveIBAByObjsNoConstraint(objWithIbaList, false);

        Map<String, String> errorMap = new HashMap<>();

        List<DescriptionResult> effectiveDescriptions = new ArrayList<>();
        objWithIbaList = new ArrayList<>();
        //分类的oid集合
        Set<String> classOidS = describeMap.keySet();
        for (String classOid : classOidS) {
            if (!partMap.containsKey(classOid)) {
                continue;
            }
            List<ResultEntityVO> resultEntityVOS = partMap.get(classOid);
            Map<String, DescriptionVO> descriptionVOMap = new HashMap<>();
            Map<BigInteger, String> partNumberOidMap = new HashMap<>();
            for (ResultEntityVO resultEntityVO : resultEntityVOS) {
                BigInteger oid = resultEntityVO.getOid();
                if (!partOidS.contains(oid.toString())) {
                    continue;
                }
                List<AttributeVO> attributeVOS = ibaValuePart.get(oid.toString());
                Map<String, List<String>> ibaMap = new HashMap<>();
                for (AttributeVO attributeVO : attributeVOS) {
                    List<String> list = new ArrayList<>();
                    list.add(attributeVO.getAttributeValue());
                    String ibaName = attributeVO.getAttributeEnName();
                    if (ibaMap.containsKey(ibaName)) {
                        List<String> strings = ibaMap.get(ibaName);
                        strings.add(attributeVO.getAttributeValue());
                        ibaMap.put(ibaName, strings);
                    } else {
                        ibaMap.put(ibaName, list);
                    }
                }
                ibaMap.putAll(map);
                GenerateDescriptionRuleDto generateDescriptionRuleDto = new GenerateDescriptionRuleDto();
                generateDescriptionRuleDto.setIbaMap(ibaMap);
                generateDescriptionRuleDto.setType(resultEntityVO.getTypeLogicalidentifier());
                generateDescriptionRuleDto.setClassId(classOid);
                generateDescriptionRuleDto.setIsCheckCurrentDescriptionIfExist("false");
                if(isW){
                    generateDescriptionRuleDto.setIsMaterial("false");
                }else {
                    if ("MaterialCode".equals(resultEntityVO.getTypeLogicalidentifier())) {
                        generateDescriptionRuleDto.setIsMaterial("true");
                    } else {
                        generateDescriptionRuleDto.setIsMaterial("false");
                    }
                }
                log.info(">>>>>>>>>>>>>>>{}", resultEntityVO.getObjectNumber());
                DescriptionVO descriptionVO;
                try {
                    descriptionVO = codeSequenceService.generateDescriptionRule(
                            generateDescriptionRuleDto, Boolean.TRUE);
                } catch (Exception e) {
                    errorMap.put(resultEntityVO.getObjectNumber(), e.getLocalizedMessage());
                    continue;
                }
                //收集图样代号
                if ("PatternCode".equals(resultEntityVO.getTypeLogicalidentifier())) {
                    descriptionVOMap.put(resultEntityVO.getObjectNumber(), descriptionVO);
                }
                SaveObjIBADTO saveObjIBADTO = new SaveObjIBADTO();
                List<IbaDTO> ibaDTOList = new ArrayList<>();
                if(isW || isT) {
                    IbaDTO ibaDTO = new IbaDTO();
                    if ("MaterialCode".equals(resultEntityVO.getTypeLogicalidentifier())) {
                        partNumberOidMap.put(resultEntityVO.getOid(), resultEntityVO.getObjectNumber());
                        ibaDTO.setKey("MaterialCodeDescription");
                        ibaDTO.setValue(descriptionVO.getSystemDescription());
                        List<String> patternCodeDescriptionList = ibaMap.get("PatternCodeDescription");
                        if(CollUtil.isNotEmpty(patternCodeDescriptionList)){
                            String str = patternCodeDescriptionList.get(0);
                            ibaDTO.setValue(str + ";" + descriptionVO.getSystemDescription());
                        }else {
                            ibaDTO.setValue(descriptionVO.getSystemDescription());
                        }
                        ibaDTOList.add(ibaDTO);
                        ibaDTO = new IbaDTO();
                        ibaDTO.setKey("Description");
                        List<String> strings = ibaMap.get("Common_Attributes|1757215074349");
                        if(CollUtil.isNotEmpty(strings)){
                            String str = strings.get(0);
                            ibaDTO.setValue(str + ";" + descriptionVO.getIbaDescription());
                        }else {
                            ibaDTO.setValue(descriptionVO.getIbaDescription());
                        }
                        ibaDTOList.add(ibaDTO);
                        saveObjIBADTO.setObjIbaList(ibaDTOList);
                    }else {
                        if ("MaterialCode".equals(resultEntityVO.getTypeLogicalidentifier())) {
                            partNumberOidMap.put(resultEntityVO.getOid(), resultEntityVO.getObjectNumber());
                            ibaDTO.setKey("MaterialCodeDescription");
                        } else {
                            ibaDTO.setKey("CompleteDescription");
                        }
                        ibaDTO.setValue(descriptionVO.getSystemDescription());
                        ibaDTOList.add(ibaDTO);
                        ibaDTO = new IbaDTO();
                        ibaDTO.setKey("Description");
                        ibaDTO.setValue(descriptionVO.getIbaDescription());
                        ibaDTOList.add(ibaDTO);
                        saveObjIBADTO.setObjIbaList(ibaDTOList);
                    }
                }else {
                    IbaDTO ibaDTO = new IbaDTO();
                    if ("MaterialCode".equals(resultEntityVO.getTypeLogicalidentifier())) {
                        partNumberOidMap.put(resultEntityVO.getOid(), resultEntityVO.getObjectNumber());
                        ibaDTO.setKey("MaterialCodeDescription");
                    } else {
                        ibaDTO.setKey("CompleteDescription");
                    }
                    ibaDTO.setValue(descriptionVO.getSystemDescription());
                    ibaDTOList.add(ibaDTO);
                    ibaDTO = new IbaDTO();
                    ibaDTO.setKey("Description");
                    ibaDTO.setValue(descriptionVO.getIbaDescription());
                    ibaDTOList.add(ibaDTO);
                    saveObjIBADTO.setObjIbaList(ibaDTOList);
                }

                // 但只在满足特定条件时收集描述信息
                if ("MaterialCode".equals(resultEntityVO.getTypeLogicalidentifier()) || "Standard".equals(
                        resultEntityVO.getTypeLogicalidentifier())) {
                    String lifecyclestagekey = resultEntityVO.getLifecyclestagekey();
                    log.info(">>>>>>>>>>>>{}", resultEntityVO.getObjectNumber());
                    log.info(">>>>>>>>>>>>{}", lifecyclestagekey);
                    if ("RELEASED".equals(lifecyclestagekey)) {
                        DescriptionResult descriptionResult = new DescriptionResult();
                        descriptionResult.setResultEntityVO(resultEntityVO);
                        descriptionResult.setIbaDTOList(ibaDTOList);
                        descriptionResult.setGenerateTime(new Date());
                        effectiveDescriptions.add(descriptionResult);
                    }
                }
                saveObjIBADTO.setCTyEntityBaseDO(
                        new CTyEntityBaseDO(resultEntityVO.getOid(), resultEntityVO.getOtype()));
                objWithIbaList.add(saveObjIBADTO);
            }
            for (SaveObjIBADTO saveObjIBADTO : objWithIbaList) {
                BigInteger oid = saveObjIBADTO.getCTyEntityBaseDO().getOid();
                if (partNumberOidMap.containsKey(oid)) {
                    String partNumber = partNumberOidMap.get(oid);
                    for (Map.Entry<String, DescriptionVO> entry : descriptionVOMap.entrySet()) {
                        String key = entry.getKey();
                        if (partNumber.contains(key)) {
                            DescriptionVO descriptionVO = entry.getValue();
                            List<IbaDTO> objIbaList = saveObjIBADTO.getObjIbaList();
                            for (IbaDTO ibaDTO : objIbaList) {
                                String value = ibaDTO.getValue();
                                if ("MaterialCodeDescription".equals(ibaDTO.getKey())) {
                                    ibaDTO.setValue(descriptionVO.getSystemDescription() + ";" + value);
                                } else if ("Description".equals(ibaDTO.getKey())) {
                                    ibaDTO.setValue(descriptionVO.getIbaDescription() + ";" + value);
                                }
                            }
                            IbaDTO ibaDTO = new IbaDTO();
                            ibaDTO.setKey("Common_Attributes|1757215074349");//完整描述
                            ibaDTO.setValue(descriptionVO.getSystemDescription());
                            objIbaList.add(ibaDTO);
                            ibaDTO = new IbaDTO();
                            ibaDTO.setKey("PatternCodeDescription");//拼接描述
                            ibaDTO.setValue(descriptionVO.getIbaDescription());
                            objIbaList.add(ibaDTO);
                        }
                    }
                }
            }
        }

        if (CollUtil.isNotEmpty(errorMap)) {
            log.info("errorMap>>>>>>>>>>>>{}", errorMap);
            throw RTErrorCodeEnum.DEV_CODE_EXIST.getException(errorMap.toString());
        }

        typlmAttributeValueService.batchSaveIBAByObjsNoConstraint(objWithIbaList, false);

        UserDO user = TyAccountContext.getUser();

        List<MaterialSapSyncDO> materialSapSyncDOList = new ArrayList<>();
        for (DescriptionResult descriptionResult : effectiveDescriptions) {
            MaterialSapSyncDO materialSapSyncDO = new MaterialSapSyncDO();
            materialSapSyncDO.setId(String.valueOf(snowflakeIdComponent.getInstance().nextId()));
            materialSapSyncDO.setMaterialCode(descriptionResult.getResultEntityVO().getObjectNumber());
            materialSapSyncDO.setMaterialVersion(
                    descriptionResult.getResultEntityVO().getVersion() + "." + descriptionResult.getResultEntityVO()
                            .getIterationid());
            materialSapSyncDO.setIsSendToSap("0");
            materialSapSyncDO.setCreateTime(new Date());
            materialSapSyncDO.setEffectiveTime(new Date());
            materialSapSyncDO.setUpdateUser(user.getOid().toString()); // 或者从上下文中获取当前用户
            materialSapSyncDOList.add(materialSapSyncDO);
        }
        // 批量插入到数据库
        if (CollUtil.isNotEmpty(materialSapSyncDOList)) {
            materialSapSyncMapper.batchInsertMaterialSapSync(materialSapSyncDOList);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttrDescribeRule(DescribeSpliceRuleDTO dto) {
        DescribeSpliceRuleDO describeSpliceRuleDO = new DescribeSpliceRuleDO();
        describeSpliceRuleDO.setClassOid(dto.getClassOid());
        describeSpliceRuleDO.setClassOtype(dto.getClassOtype());
        describeSpliceRuleDO.setDescribeRules(dto.getDescribeRules());
        describeSpliceRuleDO.setDisplayRules(dto.getDisplayRules());
        String result = mapListToDbString(dto.getNotSpliceAttrAndValue());
        describeSpliceRuleDO.setNotSplicingAttrAndValue(result);
        if (StringUtils.isNotBlank(dto.getOid())) {
            //更新
            describeSpliceRuleDO.setOid(new BigInteger(dto.getOid()));
            describeSpliceRuleMapper.updateDescribeSpliceRule(describeSpliceRuleDO);
        } else {
            //新增
            describeSpliceRuleDO.setOid(snowflakeIdComponent.getInstance().nextId());
            describeSpliceRuleMapper.insertDescribeSpliceRule(describeSpliceRuleDO);
        }
    }

    @Override
    public DescribeSpliceRuleDO queryAttrDescribeRule(IdentifierEntity entity) {
        DescribeSpliceRuleDO describeSpliceRuleDO = describeSpliceRuleMapper.queryDescribeSpliceRule(entity);
        if (ObjectUtil.isNull(describeSpliceRuleDO)) {
            return null;
        }
        List<Map<String, String>> maps = dbStringToMapList(describeSpliceRuleDO.getNotSplicingAttrAndValue());
        String jsonResult = JSON.toJSONString(maps);
        describeSpliceRuleDO.setNotSplicingAttrAndValue(jsonResult);
        return describeSpliceRuleDO;
    }


    /**
     * List<Map> → 数据库字符串（确保空键值对正确拼接）
     * 空键值对{"":""}会被拼接为"_"（空键+_+空值）
     */
    public static String mapListToDbString(List<Map<String, String>> mapList) {
        if (mapList == null || mapList.isEmpty()) {
            return "";
        }
        List<String> mapStrList = new ArrayList<>();
        for (Map<String, String> map : mapList) {
            if (map == null) {
                mapStrList.add("");
                continue;
            }
            List<String> keyValuePairs = new ArrayList<>();
            for (Map.Entry<String, String> entry : map.entrySet()) {
                // 空键/空值直接用""，不添加转义符
                String key = entry.getKey() == null ? "" : entry.getKey();
                String value = entry.getValue() == null ? "" : entry.getValue();
                keyValuePairs.add(key + KEY_VALUE_SEPARATOR + value);
            }
            // 确保每个Map至少有2个键值对，不足则补充{"":""}
            while (keyValuePairs.size() < 2) {
                keyValuePairs.add("" + KEY_VALUE_SEPARATOR + ""); // 拼接为"_"
            }
            mapStrList.add(String.join(KEY_VALUE_SEPARATOR, keyValuePairs));
        }
        return String.join("|", mapStrList); // 存储时用|分隔
    }

    /**
     * 数据库字符串转换为List<Map>，确保每个Map有2个键值对
     * 规则：若解析后只有1个键值对，自动补充{"":""}作为第二个
     */
    public static List<Map<String, String>> dbStringToMapList(String dbString) {
        List<Map<String, String>> resultList = new ArrayList<>();
        if (dbString == null || dbString.isEmpty()) {
            return resultList;
        }
        // 按|分割得到每个Map的字符串
        String[] mapStrs = dbString.split(MAP_SEPARATOR, -1);
        for (String mapStr : mapStrs) {
            Map<String, String> map = new LinkedHashMap<>();
            if (mapStr.isEmpty()) {
                // 空字符串直接添加两个空键值对
                map.put("", "");
                map.put("", "");
                resultList.add(map);
                continue;
            }
            // 按_分割得到当前Map中的所有key和value
            String[] parts = mapStr.split("_", -1);
            List<String> keyValueList = new ArrayList<>(Arrays.asList(parts));
            // 若键值对数量为单数（即长度为奇数），补充一个空值凑成偶数
            if (keyValueList.size() % 2 != 0) {
                keyValueList.add(""); // 补充空value，使总长度为偶数
            }
            // 按2个元素一组添加到Map（确保每组有两个键值对）
            for (int i = 0; i + 1 < keyValueList.size(); i += 2) {
                String key = keyValueList.get(i);
                String value = keyValueList.get(i + 1);
                map.put(key, value);
            }
            // 若最终键值对数量不足2个，补充空键值对
            while (map.size() < 2) {
                map.put("", "");
            }
            resultList.add(map);
        }
        return resultList;
    }

    @Override
    public DescriptionRuleVO spliceDescriptionRules(List<DescriptionRuleDTO> list) {
        if (CollUtil.isEmpty(list)) {
            return new DescriptionRuleVO();
        }

        List<DescriptionRuleDTO> sortedList = list.stream()
                .sorted(Comparator.comparing(DescriptionRuleDTO::getNo))
                .collect(Collectors.toList());

        String names = sortedList.stream()
                .map(DescriptionRuleDTO::getName)
                .collect(Collectors.joining("_"));

        String displayNames = sortedList.stream()
                .map(DescriptionRuleDTO::getDisplayName)
                .collect(Collectors.joining("_"));

        DescriptionRuleVO vo = new DescriptionRuleVO();
        vo.setName(names);
        vo.setDisplayName(displayNames);

        return vo;
    }

    @Override
    public List<String> queryAllProductLine(BigInteger parentoid) {
        return rtClassificationMapper.queryAllProductLine(parentoid);
    }

    /**
     * 描述结果数据类
     */
    @Data
    public static class DescriptionResult {
        private ResultEntityVO resultEntityVO;
        private List<IbaDTO> ibaDTOList;
        private Date generateTime;                     // 生成时间
    }


    @Override
    public void checkEnumByClassId(HandleEnumItemDTO handleEnumItemDTO) {
        EnumerationDefDO enumerationDefDO = typlmEnumerationMapper.selectByPrimaryKey(handleEnumItemDTO.getDefoid());
        List<JSONObject> jsonObjects = rtTypeClassMapper.selectEnumOidByClassOid(
                handleEnumItemDTO.getDefoid().toString());
        log.info(">>>>>>>>>>>>>>");
    }

    /**
     * 将列表平分成指定份数
     */
    private <T> List<List<T>> splitList(List<T> originalList, int chunkCount) {
        if (CollUtil.isEmpty(originalList) || chunkCount <= 0) {
            return Collections.emptyList();
        }

        List<List<T>> chunks = new ArrayList<>();
        int totalSize = originalList.size();
        int chunkSize = (int) Math.ceil((double) totalSize / chunkCount);

        for (int i = 0; i < chunkCount; i++) {
            int fromIndex = i * chunkSize;
            int toIndex = Math.min(fromIndex + chunkSize, totalSize);

            if (fromIndex < totalSize) {
                chunks.add(originalList.subList(fromIndex, toIndex));
            }
        }

        return chunks;
    }

}